package com.qn.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qn.common.enums.RedisKeyConstants;
import com.qn.entity.I18nMsg;
import com.qn.mapper.I18nMsgMapper;
import com.qn.service.I18nMsgService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Locale;
import java.util.Set;

@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class I18nMsgServiceImpl extends ServiceImpl<I18nMsgMapper, I18nMsg> implements I18nMsgService {

    private final RedisTemplate<String, Object> redisTemplate;

    @Override
    public void init(List<I18nMsg> errorCodeList) {
        if (CollUtil.isEmpty(errorCodeList)) {
            return;
        }
        // 清空缓存
        deleteKeysWithPrefix(RedisKeyConstants.I18N_MSG);

        // 查询所有的error code
        List<I18nMsg> allCodeList = this.lambdaQuery().select(I18nMsg::getId, I18nMsg::getCode).list();
        if (CollUtil.isEmpty(allCodeList)) {
            // 插入
            this.saveBatch(errorCodeList);
        }

        List<Integer> dbCodeList = allCodeList.stream().map(I18nMsg::getCode).toList();
        // 过滤掉数据库中已存在的code
        List<I18nMsg> saveCodeList = errorCodeList.stream().filter(code -> !dbCodeList.contains(code.getCode())).toList();
        // 插入
        this.saveBatch(saveCodeList);

        List<Integer> nativeCodeList = errorCodeList.stream().map(I18nMsg::getCode).toList();
        // 过滤掉错误码中不存在的code
        List<I18nMsg> deleteCodeList = allCodeList.stream().filter(code -> !nativeCodeList.contains(code.getCode())).toList();
        // 删除
        this.removeByIds(deleteCodeList);
    }

    public void deleteKeysWithPrefix(String prefix) {
        Set<String> keys = redisTemplate.keys(prefix + "*");
        if (!keys.isEmpty()) {
            redisTemplate.delete(keys);
        }
    }

    @Override
    @Cacheable(value = RedisKeyConstants.I18N_MSG, key = "#code", unless = "#result == null")
    public I18nMsg getI18nMsg(Locale locale, String code) {
        LambdaQueryWrapper<I18nMsg> queryWrapper = new LambdaQueryWrapper<>();
        if (StrUtil.isNumeric(code)) {
            queryWrapper.eq(I18nMsg::getCode, Integer.parseInt(code));
        } else {
            queryWrapper.eq(I18nMsg::getKeyCode, code);
        }
        queryWrapper.eq(I18nMsg::getLocale, locale.toString());
        return this.getOne(queryWrapper);
    }

    @Override
    public void saveI18nMsg(I18nMsg i18nMsg) {
        this.save(i18nMsg);
    }

    @Override
    @CacheEvict(cacheNames = RedisKeyConstants.I18N_MSG,
            allEntries = true) // allEntries 清空所有缓存，因为 id 不是直接的缓存 code，不好清理
    public void updateI18nMsg(I18nMsg i18nMsg) {
        this.updateById(i18nMsg);
    }

    @Override
    @CacheEvict(cacheNames = RedisKeyConstants.I18N_MSG,
            allEntries = true) // allEntries 清空所有缓存，因为 id 不是直接的缓存 code，不好清理
    public void deleteI18nMsg(Long id) {
        this.removeById(id);
    }

}
